package com.yy.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yy.entity.Employee;
import com.yy.mapper.EmployeeMapper;
import com.yy.service.EmployeeService;
import com.yy.utils.MD5Utils;
import com.yy.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * create by KongFuning on 2022/7/30
 */
@Slf4j
@Service
public class EmployeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements EmployeeService {

//    @Resource
//    private StringRedisTemplate stringRedisTemplate;

    /*
    * 登录
    * */
    @Override
    public R login(HttpServletRequest request,Employee employee) {
        // 把用户输入的密码 转换为MD5 加密格式
        String md5Password = MD5Utils.code(employee.getPassword());
        // 1、查询数据库
        LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Employee::getUsername,employee.getUsername())
                    .eq(Employee::getPassword,md5Password);
        Employee emp = getOne(queryWrapper);
        if(emp == null){
            // 2、数据库不存在
            return R.error("用户名或密码错误！");
        }
        if(emp.getStatus() == 0){
            return R.error("该用户已被封禁！");
        }
        // 3、登录成功，将id存入session并返回登录成功结果
        request.getSession().setAttribute("employee",emp.getId());
        return R.success(emp);
    }


    /*
    * 登出
    * */
    @Override
    public R logout(HttpServletRequest request) {
        request.getSession().removeAttribute("employee");
        return R.success("退出成功");
    }


    /*
    * 分页
    * */
    @Override
    public R<Page> pageEmployees(Integer page, Integer pageSize, String name) {
        log.info("page:{},pageSize:{},name:{}",page,pageSize,name);
        Page<Employee> employeePage = new Page<>(page,pageSize);
        getPageMap(employeePage, name);
        return R.success(employeePage);
    }

    public Page getPageMap(Page<Employee> employeePage,String name){
        // 1、定义条件 如果有条件，则带上条件查，没有则不带
        LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StrUtil.isNotEmpty(name),Employee::getName,name);
        queryWrapper.orderByDesc(Employee::getUpdateTime);
        // 2、分页的所有数据都封装在employeePage中了
        page(employeePage,queryWrapper);
        return employeePage;
    }


    /*
    * 添加员工
    * */
    @Override
    public R saveEmployee(Employee employee) {
        // 判断账号是否已经存在
        Employee emp = query().eq("username", employee.getUsername()).one();
        if(emp != null){
            // 表示该员工已存在，提示错误信息
            return R.error("员工：【" + employee.getUsername() + "】已存在！");
        }
        // 设置初始密码 123456，需要进行md5加密
        employee.setPassword(MD5Utils.code("123456"));
        // 添加到数据库
        boolean result = save(employee);
        if(result){
            return R.success("添加员工成功！");
        }
        return R.error("添加员工失败！");
    }

    /*
    * 编辑员工反查详情
    * */
    @Override
    public R toUpdate(String id) {
        // 根据id查询员工
        Employee emp = getById(id);
        return R.success(emp);
    }

    /*
    * 修改员工信息
    * */
    @Override
    public R updateEmployee(Employee employee) {
        updateById(employee);
        return R.success("修改员工成功！");
    }

    //【用Redis优化的管理员登录】
    /*
    *
    @Override
    public R login(Employee employee) {
        // 对于用户输入的密码 进行 MD5加密后与数据库比对
        String md5Password = MD5Utils.code(employee.getPassword());

        // 加入Redis缓存 并解决缓存穿透问题（缓存空值）
        // 1、从redis中查询用户缓存
        String json = stringRedisTemplate.opsForValue().get("login:employee:" + employee.getUsername());
        // 2、判断是否存在
        if(StrUtil.isNotBlank(json)){
            // 存在 判断密码是否正确
            Employee emp = JSONUtil.toBean(json,Employee.class);
            if(!md5Password.equals(emp.getPassword())){
                return R.error("密码错误！");
            }
            return R.success(emp);
        }
        // 4、判断命中的是否是空值
        if(json != null){
            return R.error("用户不存在！");
        }
        // 5、redis中不存在，去数据库查
        Employee emp = query().eq("username",employee.getUsername()).one();
        // 6、数据库中也不存在
        if(emp == null){
            // 将空值写入redis
            stringRedisTemplate.opsForValue().set("login:employee:" + employee.getUsername(),""
                    ,2L, TimeUnit.MINUTES);
            return R.error("用户不存在！");
        }
        // 数据库中存在，判断密码是否正确
        if(!md5Password.equals(emp.getPassword())){
            // 密码错误，也把数据库正确信息存入redis
            // 因为在redis层面也做了判断，这样做防止用户第一次输入正确的用户名而多次密码错误，每一次都要去查数据库
            stringRedisTemplate.opsForValue().set("login:employee:" + employee.getUsername()
                    ,JSONUtil.toJsonStr(emp)
                    ,30L,TimeUnit.MINUTES);
            return R.error("密码错误！");
        }
        // 判断用户是否被封禁
        if(emp.getStatus() == 0){
            return R.error("此用户已被封禁！");
        }
        // 数据库中用户和密码都正确，存入redis中
        stringRedisTemplate.opsForValue().set("login:employee:" + employee.getUsername()
                ,JSONUtil.toJsonStr(emp)
                ,30L,TimeUnit.MINUTES);

        // 设置token令牌 作为登录凭证
        String token = UUID.randomUUID().toString(true);
        // 将employee对象转换为hash存储
        Map<String, Object> employeeMap = BeanUtil.beanToMap(emp,new HashMap<>(),
                CopyOptions.create().setIgnoreNullValue(true).
                        setFieldValueEditor((fieldName,fieldValue) -> fieldValue.toString()));
        // 存储token
        stringRedisTemplate.opsForHash().putAll("login:employee:" + token,employeeMap);
        // 设置token有效期 30min
        stringRedisTemplate.expire("login:employee:" + token, 30L,TimeUnit.MINUTES);

        return R.success(emp);
    }

    */

}

